package Controller

import (
	"github.com/gin-gonic/gin"
	"github.com/jinzhu/gorm"
	"golang.org/x/crypto/bcrypt"
	"learningProject/vueGoProject/common"
	"learningProject/vueGoProject/dto"
	"learningProject/vueGoProject/model"
	"learningProject/vueGoProject/response"
	"learningProject/vueGoProject/utils"
	"log"
	"net/http"
)

func Register(c *gin.Context) {
	// json形式的请求参数
	var requestUser = model.User{}
	// json.NewDecoder(c.Request.Body).Decode(&requestUser)
	c.Bind(&requestUser) // gin提供的json绑定解析，和上面一行效果一样
	name := requestUser.Name
	telephone := requestUser.Telephone
	password := requestUser.Password

	// 获取参数
	// 只能接受表单传参,像ajax、aiox这种的表单都是json传参的，不能用
	//name := c.PostForm("name")
	//telephone := c.PostForm("telephone")
	//password := c.PostForm("password")
	// 数据验证
	if len(telephone) != 11 {
		response.Response(c, http.StatusUnprocessableEntity, 422, nil, "手机号必须为11位!")
		return
	}
	if len(password) < 6 {
		response.Response(c, http.StatusUnprocessableEntity, 422, nil, "密码不能少于6位!")
		return
	}
	// 如果没传用户名，随机生成一个十位的随机字符串
	if len(name) == 0 {
		name = utils.RandomString(10)
	}
	// 判断手机号是否存在
	if isTelephoneExist(common.DB, telephone) {
		response.Response(c, http.StatusUnprocessableEntity, 422, nil, "该手机号已被注册！")
		return
	}

	// 创建用户
	// 密码不能明文保存，加密用户密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		response.Response(c, http.StatusInternalServerError, 500, nil, "密码加密错误！")
		return
	}
	newUser := model.User{
		Name:      name,
		Telephone: telephone,
		Password:  string(hashedPassword),
	}
	common.DB.Create(&newUser)

	// 注册后直接用token登录，无需跳转到登录界面
	// 发放token
	token, err := common.ReleaseToken(newUser)
	if err != nil {
		response.Response(c, http.StatusInternalServerError, 500, nil, "token发放错误！")
		log.Printf("token发放错误！")
		return
	}
	// 返回结果
	response.Success(c, gin.H{"token": token}, "注册成功")
}

func Login(c *gin.Context) {
	// 获取参数
	telephone := c.PostForm("telephone")
	password := c.PostForm("password")

	// 数据验证
	if len(telephone) != 11 {
		response.Response(c, http.StatusUnprocessableEntity, 422, nil, "手机号必须为11位！")
		return
	}
	if len(password) < 6 {
		response.Response(c, http.StatusUnprocessableEntity, 422, nil, "密码不能少于6位！")
		return
	}

	// 判断手机号是否存在
	var user model.User
	common.DB.Where("telephone=?", telephone).First(&user)
	if user.ID == 0 {
		response.Response(c, http.StatusUnprocessableEntity, 422, nil, "用户不存在！")
		return
	}

	// 验证密码是否正确
	if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
		response.Response(c, http.StatusBadRequest, 400, nil, "密码错误！")
		return
	}

	// 发放token
	token, err := common.ReleaseToken(user)
	if err != nil {
		response.Response(c, http.StatusInternalServerError, 500, nil, "token发放错误！")
		log.Printf("token发放错误！")
		return
	}

	// 返回结果
	response.Success(c, gin.H{"token": token}, "登录成功")
}

func Info(c *gin.Context) {
	user, _ := c.Get("user")         // 用户通过验证后可以直接从上下文中获取信息
	user2 := user.(model.User)       // 类型断言
	userDto := dto.ToUserDto(&user2) // 只有先定义变量接受类型断言后才能用指针
	response.Success(c, gin.H{"user": userDto}, "")
}

func isTelephoneExist(DB *gorm.DB, telephone string) bool {
	var user model.User
	DB.Where("telephone=?", telephone).First(&user)
	if user.ID != 0 {
		return true
	}
	return false
}
